package rabbit.flt.r2dbc.test.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.r2dbc.core.R2dbcEntityTemplate;
import org.springframework.data.relational.core.query.Query;
import org.springframework.data.relational.core.query.Update;
import org.springframework.stereotype.Service;
import rabbit.flt.r2dbc.test.User;
import reactor.core.publisher.Mono;

import static org.springframework.data.relational.core.query.Criteria.where;

@Service
public class R2dbcService {

    @Autowired
    protected R2dbcEntityTemplate template;

    public Mono<User> add(String name) {
        User user = new User();
        user.setUsername(name);
        return template.insert(user);
    }

    public Mono<Integer> delete(String name) {
        return template.delete(Query.query(where("username").is(name)), User.class);
    }

    public Mono<Integer> update(String old, String newName) {
        return template.update(Query.query(where("username").is(old)), Update.update("username", newName), User.class);
    }

    public Mono<User> select(String name) {
        return template.selectOne(Query.query(where("username").is(name)), User.class);
    }

    public Mono<User> selectFirst(String username) {
        String sql = "select * from user_info where username = :username limit 0, 1";
        return template.getDatabaseClient().sql(sql).bind("username", username).map(r -> {
            User user = new User();
            user.setUsername((String) r.get("username"));
            return user;
        }).all().collectList().map(list -> list.get(0));
    }

    public Mono<Long> multiAdd(String username) {
        User user = new User();
        user.setUsername(username);
        return template.insert(user).then(Mono.defer(() -> {
            user.setId(null);
            return template.insert(user);
        })).then(Mono.defer(() -> {
            user.setId(null);
            return template.insert(user);
        })).then(Mono.defer(() -> {
            user.setId(null);
            return template.insert(user);
        })).then(Mono.defer(() -> {
            user.setId(null);
            return template.insert(user);
        })).then(template.count(Query.query(where("username").is(username)), User.class));
    }

    public Mono<Void> errorSql() {
        String sql = "* from user_info limit 0, 1";
        return template.getDatabaseClient().sql(sql).map(r -> {
            User user = new User();
            user.setUsername((String) r.get("username"));
            return user;
        }).all().collectList().then();
    }
}
